/*
 ******************************************************************************
 * @file    read_data_polling.c
 * @author  Sensors Software Solution Team
 * @brief   This file shows how to extract data from the sensor in
 *          polling mode.
 *
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */

/*
 * This example was developed using the following STMicroelectronics
 * evaluation boards:
 *
 * - STEVAL_MKI109V3 + STEVAL-MKI105V1
 * - NUCLEO_F411RE + X_NUCLEO_IKS01A3 + STEVAL-MKI105V1
 *
 * and STM32CubeMX tool with STM32CubeF4 MCU Package
 *
 * Used interfaces:
 *
 * STEVAL_MKI109V3    - Host side:   USB (Virtual COM)
 *                    - Sensor side: SPI(Default) / I2C(supported)
 *
 * NUCLEO_STM32F411RE - Host side: UART(COM) to USB bridge
 *                    - Sensor side: I2C(Default) / SPI(supported)
 *
 * If you need to run this example on a different hardware platform a
 * modification of the functions: `platform_write`, `platform_read`,
 * `tx_com` and 'platform_init' is required.
 *
 */

/* STMicroelectronics evaluation boards definition
 *
 * Please uncomment ONLY the evaluation boards in use.
 * If a different hardware is used please comment all
 * following target board and redefine yours.
 */
//#define STEVAL_MKI109V3
#define NUCLEO_F411RE

#if defined(STEVAL_MKI109V3)
/* MKI109V3: Define communication interface */
#define SENSOR_BUS hspi2

/* MKI109V3: Vdd and Vddio power supply values */
#define PWM_3V3 915

#elif defined(NUCLEO_F411RE)
/* NUCLEO_F411RE: Define communication interface */
#define SENSOR_BUS hi2c1

#endif

/* Includes ------------------------------------------------------------------*/
#include <string.h>
#include <stdio.h>
#include "readXYZ.h"
#include "iwdg.h"
#include "stm32l4xx_hal.h"
#include "lis3dh_reg.h"
#include "gpio.h"
#include "i2c.h"
#if defined(STEVAL_MKI109V3)
#include "usbd_cdc_if.h"
#include "spi.h"
#elif defined(NUCLEO_F411RE)
#include "usart.h"
#endif

typedef union {
	int16_t i16bit[3];
	uint8_t u8bit[6];
} axis3bit16_t;

/* Private macro -------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
static axis3bit16_t data_raw_acceleration;
static uint16_t data_raw_temperature;
static float acceleration_mg[3];
static float temperature_degC;
static uint8_t whoamI;
static uint8_t tx_buffer[1000];
stmdev_ctx_t dev_ctx;
/* Extern variables ----------------------------------------------------------*/

/* Private functions ---------------------------------------------------------*/
/*
 *   WARNING:
 *   Functions declare in this section are defined at the end of this file
 *   and are strictly related to the hardware platform used.
 *
 */
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,
		uint16_t len);
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
		uint16_t len);
static void tx_com(uint8_t *tx_buffer, uint16_t len);
static void platform_delay(uint32_t ms);
static void platform_init(void);

/* Main Example --------------------------------------------------------------*/

void init_lis3dh(void) {
	dev_ctx.write_reg = platform_write;
	dev_ctx.read_reg = platform_read;
	dev_ctx.handle = &SENSOR_BUS;

	/* Wait boot time and initialize platform specific hardware */
	platform_init();

	/* Wait sensor boot time */
	platform_delay(5);

	/* Check device ID */
	lis3dh_device_id_get(&dev_ctx, &whoamI);
	while (whoamI != LIS3DH_ID) {
		HAL_Delay(100);
		HAL_IWDG_Refresh(&hiwdg);
		lis3dh_device_id_get(&dev_ctx, &whoamI);
		printf("INIT FAIL\n");
		/* manage here device not found */
	}

	/* Enable Block Data Update. */
	lis3dh_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);

	/* Set Output Data Rate to 1Hz. */
	lis3dh_data_rate_set(&dev_ctx, LIS3DH_ODR_400Hz);

	/* Set full scale to 2g. */
	lis3dh_full_scale_set(&dev_ctx, LIS3DH_8g);

	/* Enable temperature sensor. */
	lis3dh_aux_adc_set(&dev_ctx, LIS3DH_AUX_ON_TEMPERATURE);

	/* Set device in continuous mode with 12 bit resol. */
	lis3dh_operating_mode_set(&dev_ctx, LIS3DH_HR_12bit);
}

float* lis3dh_read_data_polling(void) {
	/* Initialize mems driver interface */
	static float data_list[BACK_SIZE * 3];
	uint8_t num = 0;

	/* Read samples in polling mode (no int) */
	lis3dh_reg_t reg;
	while (num < BACK_SIZE) {
		lis3dh_xl_data_ready_get(&dev_ctx, &reg.byte);
		if (reg.byte) {
			/* Read accelerometer data */
			memset(data_raw_acceleration.u8bit, 0x00, 3 * sizeof(int16_t));
			lis3dh_acceleration_raw_get(&dev_ctx, data_raw_acceleration.u8bit);
			data_list[num * 3] = lis3dh_from_fs2_hr_to_mg(
					data_raw_acceleration.i16bit[0]);
			data_list[num * 3 + 1] = lis3dh_from_fs2_hr_to_mg(
					data_raw_acceleration.i16bit[1]);
			data_list[num * 3 + 2] = lis3dh_from_fs2_hr_to_mg(
					data_raw_acceleration.i16bit[2]);

			num++;
		}
	}

	return data_list;
	/* Read output only if new value available */

}

/*
 * @brief  Write generic device register (platform dependent)
 *
 * @param  handle    customizable argument. In this examples is used in
 *                   order to select the correct sensor bus handler.
 * @param  reg       register to write
 * @param  bufp      pointer to data to write in register reg
 * @param  len       number of consecutive register to write
 *
 */
static int32_t platform_write(void *handle, uint8_t reg, uint8_t *bufp,
		uint16_t len) {
	if (handle == &hi2c1) {
		/* Write multiple command */
		reg |= 0x80;
		HAL_I2C_Mem_Write(handle, LIS3DH_I2C_ADD_H, reg,
		I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);
	}
#if defined(STEVAL_MKI109V3)
  else if (handle == &hspi1) {
    /* Write multiple command */
    reg |= 0x40;
    HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(handle, &reg, 1, 1000);
    HAL_SPI_Transmit(handle, bufp, len, 1000);
    HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_SET);
  }
#endif
	return 0;
}

/*
 * @brief  Read generic device register (platform dependent)
 *
 * @param  handle    customizable argument. In this examples is used in
 *                   order to select the correct sensor bus handler.
 * @param  reg       register to read
 * @param  bufp      pointer to buffer that store the data read
 * @param  len       number of consecutive register to read
 *
 */
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
		uint16_t len) {
	if (handle == &hi2c1) {
		/* Read multiple command */
		reg |= 0x80;
		HAL_I2C_Mem_Read(handle, LIS3DH_I2C_ADD_H, reg,
		I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);
	}
#if defined(STEVAL_MKI109V3)
  else if (handle == &hspi2) {
    /* Read multiple command */
    reg |= 0xC0;
    HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_RESET);
    HAL_SPI_Transmit(handle, &reg, 1, 1000);
    HAL_SPI_Receive(handle, bufp, len, 1000);
    HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_SET);
  }
#endif
	return 0;
}

/*
 * @brief  Send buffer to console (platform dependent)
 *
 * @param  tx_buffer     buffer to trasmit
 * @param  len           number of byte to send
 *
 */
static void tx_com(uint8_t *tx_buffer, uint16_t len) {
#if defined(STEVAL_MKI109V3)
  CDC_Transmit_FS(tx_buffer, len);
#elif defined(NUCLEO_F411RE)
	HAL_UART_Transmit(&huart2, tx_buffer, len, 1000);
#endif
}

/*
 * @brief  platform specific delay (platform dependent)
 */
static void platform_delay(uint32_t ms) {
	HAL_Delay(ms);
}

/*
 * @brief  platform specific initialization (platform dependent)
 */
static void platform_init(void) {
#if defined(STEVAL_MKI109V3)
  TIM3->CCR1 = PWM_3V3;
  TIM3->CCR2 = PWM_3V3;
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);
  HAL_Delay(1000);
#endif
}

